SIMD์ ๊ดํ ๊ฐ๋จํ ์ ๋ฆฌ. ์๊ฒ ๋์๋๋ฐ ์ ๋ฆฌ ์ํ๋ฉด ๋์ค์ ๋ค์ ๋งจ๋
์์ ๊ตฌ๊ธ๋ง ํด์ผํ๋ฏ๋ก ํ๋ฒ ์๊ฒ ๋ ๋ด์ฉ ์ ๋ฆฌํ๊ณ ๊ฐ๋ณด๋ ค๊ณ ํ๋ค.
SIMD๋ Single Instruction Multiple Data์ ์ฝ์์ด๋ค. Vectorization๊ณผ ๊ด๋ จ์๋๋ฐ, ๋ณดํต ๊ทธ๋ํฝ ์ธ๊ณ์์๋ ํ๋์ Instruction์ผ๋ก ์ฌ๋ฌ๊ฐ์ ์์น์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋์์ ์กฐ์ํ ํ์๊ฐ ์๋ค. ์๋ฅผ ๋ค์ด, ์์์ ๋ฐ์ ์ํค๋ operation์ ๊ฒฝ์ฐ ์ ์ฒด ํฝ์
์ ๋ํด ์์ ๋นํธ๋ฅผ ๋ค์ง์ด์ผ ํ ๊ฒ์ด๋ค. ์ด๋ฌํ ์์
๋ค์ ๊ผญ ๊ทธ๋ํฝ์ ๊ตญํ๋์ง ์๋๋ผ๋, ์ผ๋ฐ์ ์ผ๋ก ํ์ํ ๊ฒฝ์ฐ๋ค์ด ๋ง์ด ์๋ค. ๋จธ์ ๋ฌ๋์์๋ผ๋์ง.. ๊ทธ๋์ ์์ ๋ถํฐ majorํ CPU๋ค์์ ์ง์์ด ์ด๋ฃจ์ด์ง๊ณ ์์ผ๋ฉฐ, Intel CPU๋ ์ด๋ฅผ avx ๋ผ๋ ์ด๋ฆ์ผ๋ก ์ง์ํ๋ค.
avx๋ Advanced Vector Extensions์ ์ฝ์์ด๋ค. ์ฒ์์๋ 128 bits ๋จ์์ ๋ณ๋ ฌ์ฐ์ฐ์ด ์ง์๋๋ค๊ฐ, ํ์ฌ ๊ฐ์ข
์จ๋ผ์ธ PS ์ฌ์ดํธ๋ค(ex: codeforces, BOJ)์ ๊ฒฝ์ฐ avx2, 256 bits ๋จ์๋ฅผ ์ฌ์ฉํ ์ ์๊ณ , ์ต๊ทผ์ ์ข์ Intel CPU๋ 512 bits๊น์ง๋ ์ง์์ด ๋๋ค.
๋ง๋ง ๋ค์ด์๋ ๋ณ๋ ฌ์ฐ์ฐ ์ฒด๊ฐ์ด ์ ์๋ ์ ์๋๋ฐ, ๊ตฌ์ฒด์ ์ธ ์์๋ฅผ ๋ค์ด๋ณด๋ฉด 256 bits ๋จ์๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ๋ฅผ ๊ธฐ์ค์ผ๋ก 16๋นํธ ์ ์(short)๋ฅผ ๊ธฐ๋ณธ ์๋ฃํ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ๋์์ size๊ฐ 16์ธ vector์ ์ฐ์ฐ์ด ๊ฐ๋ฅํ๋ค๋ ๋ป์ด๋ค. ์๊ฐ๋ณต์ก๋๊ฐ ์ ์งํ๊ฒ ์ผ๋ก ์ค์ด๋๋ ํจ๊ณผ๋ฅผ ๋ณผ ์ ์๊ฒ ๋ค. bitset์ ๋น์ทํ๊ฒ ์ฌ์ฉํ๋ ๋๋์ด ์๋ค. ์ด๊ฒ๋ ์์์๊ฐ์ ์ค์ด๊ธฐ ์ํด ํ์ฉ๋๋ ๊ฒฝ์ฐ๋ค์ด ์์ด์..
์ผ๋จ ์ด ๊ธ์์๋ immintrin.h๋ฅผ include ํด์ ์ฌ์ฉํ๋ ๊ฒ(aka ์์ฌ๋)์ ๊ธฐ์ค์ผ๋ก ํ๋ฒ ์์๋ณด๊ฒ ๋ค. Auto Vectorization์ด๋ ๊ฒ๋ ์๋๋ฐ, ์ด๊ฒ์ ๊ทธ๋ฅ ์ปดํ์ผ ์ต์
์ผ๋ก ์ผ๋ฉด ์ปดํ์ผ๋ฌ๊ฐ ์์์ ์ต์ ํ ํด์ฃผ๋ ๊ฒ์ด๋ค. ์ด๊ฑฐ๋ ๊ทธ๋ฅ ํ๋๊ทธ๋ง ์ถ๊ฐํ๋ฉด ๋๋ ๊ฒ์ด๋ผ ๋ฐ๋ก ๊ธ๋ก ๋ค๋ฃจ๊ธฐ์๋ ์ ๋งคํ ์์ญ์ด๋ผ..
์๋ง PS์ ์ฌ์ทจํ๋ค๊ฐ ๋ค๋ฅธ ์ฌ๋๋ค์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์๋์ ๊ฐ์ header๋ฅผ ์ข ์ข ๋ณด๊ณค ํ์ ๊ฒ์ด๋ค.
#pragma GCC optimize ("O3")#pragma GCC optimize ("Ofast")#pragma GCC optimize ("unroll-loops")#pragma GCC target("sse,sse2,sse3,ssse3,sse4,avx,avx2")
์ด๊ฒ์ ์ฌ์ค PS ์์คํ
์์ ๋ง์ผ๋ ค๋ฉด ๋ง์ ์๋ ์๋ ๋ถ๋ถ์ธ๋ฐ, ์ปดํ์ผ๋ฌ์๊ฒ ๊ฐ์ ๋ก ์ด๋ค ๊ธฐ๋ฅ์ ์ผค ๊ฒ์ธ์ง์ ๋ํด์ pragma ํ๋๊ทธ๋ฅผ ํตํด์ ์๋ ค์ฃผ๋ ๊ฒ์ด๋ค. ์ด ์ค์์, avx, avx2๋ฅผ taget์ผ๋ก ์ง์ ํ๋ ๋ถ๋ถ์ด ์๋๋ฐ, ์ด๊ฒ๊ณผ ๋๋ถ์ด, ์๋ header๋ฅผ include ํ๋ฉด ์ด์ SIMD๋ฅผ ์ฌ์ฉํ ์ค๋น๊ฐ ๋๋๋ค.
#include <immintrin.h>
์ด ๋ฌธ์ ๋ ๊ฐ ์ฟผ๋ฆฌ๊ฐ ์คํ๋๋ ์์๊ฐ ๋ฐ๋๊ฒ ๋๋ฉด ๊ฒฐ๊ณผ๊ฐ ๋ฐ๋๊ธฐ ๋๋ฌธ์, ์ด๋ป๊ฒ ํ๋ฉด ์ ์ฒด ๊ตฌ๊ฐ์ ๋ํด์ ๋น ๋ฅด๊ฒ ์ฐ์ฐ์ ํ ์ ์๋์ง๊ฐ ๊ด๊ฑด์ด๊ณ , SIMD๋ฅผ ๋ผ์น๊ธฐ ๋ฑ ์ข์ ์กฐ๊ฑด์ด๋ผ๊ณ ํ ์ ์๊ฒ ๋ค. ์ด๋ค vector๊ฐ ์๋ค๋ฉด, ๋์์ ๋บ์
์ ์ ์ฉํ๋ฉด์ ์ ๋๊ฐ์ ์ ์ฉํ๋ฉด ๋๋๋ฐ, ๋ ๋ค avx2์์ ์ง์ํ๋ ๋ช
๋ น์ด์ด๋ค.
#pragma GCC optimize ("O3")#pragma GCC optimize ("Ofast")#pragma GCC optimize ("unroll-loops")#pragma GCC target("sse,sse2,sse3,ssse3,sse4,avx,avx2")#include <bits/stdc++.h>using namespace std;#include <immintrin.h>alignas(32) int bucket[400][512], TMP[8];alignas(32) int bucketLazy[400][200'000];alignas(32) int bucketLazySz[400];
์ฌ๊ธฐ์ alignas(32) ๋ถ๋ถ์ ์ ์ํด์ ๋ด์ผํ๋๋ฐ, ์ด๊ฒ์ SIMD๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ์ ์ฝ์กฐ๊ฑด์ด๋ผ๊ณ ๋ณด๋ฉด ๋๊ฒ ๋ค. ํด๋น ์๋ฃํ์ ํฌ๊ธฐ๋ก align ๋์ด์ผ ํ๋ค. ๋ฉ๋ชจ๋ฆฌ์ ํน์ ์ฃผ์๋ก๋ถํฐ ์์ํด์ผ ์ ์์ ์ผ๋ก ๋์ํ๊ธฐ ๋๋ฌธ์, ๊ผญ ๋ฃ์ด์ค์ผ ํ๋ ์ต์
์ด๋ค. ๋ง์ฝ short๋ฅผ ์ด๋ค๋ฉด alignas(16)์ด ๋๋ฉด ๋๋ค.
inline void handleLazy(int b) {for(int j = 0; j < bucketLazySz[b]; ++j) {int& d = bucketLazy[b][j];*(__m256i*) TMP = _mm256_set_epi32(d, d, d, d, d, d, d, d);int* w = bucket[b];for(int i = 0; i < 64; ++i) {*(__m256i*)w = _mm256_sub_epi32(*(__m256i*)w, *(__m256i*) TMP);*(__m256i*)w = _mm256_abs_epi32(*(__m256i*)w);w += 8;}}bucketLazySz[b] = 0;}
๋์ ๊ฒฝ์ฐ์๋ ๊ฐ bucket์ 512 ํฌ๊ธฐ๋ก ๋๋ ์ ๊ณ ์ ๋ ํฌ๊ธฐ์ ๊ณต๊ฐ์ Lazy์ฐ์ฐ์ ์ํํ ๋ SIMD๋ฅผ ์ฌ์ฉํ๋ค. ์๋๊ฐ์ผ๋ฉด ๊ฐ bucket๋ณ๋ก ๋ฃจํ๋ฅผ 512๋ฒ ๋์์ผ๊ฒ ์ง๋ง, ์์ฒ๋ผ ํ๋ฉด 8๋ฐฐ๋ก ์ค์ด๋ 64๋ฒ๋ง์ ์ํ์ ์๋ฃ์ํฌ ์ ์๋ค.
์ฝ๋์ ๋ํ๋๋ _mm256์ผ๋ก ์์๋๋ ๊ฒ์ 256 bits ๊ณต๊ฐ์ ๊ธฐ์ค์ผ๋ก ์ฐ์ฐ์ด ์ผ์ด๋๋ค๋ ๋ป์ด๋ฉฐ, ์
๋ ฅ๊ฐ๊ณผ ์ถ๋ ฅ๊ฐ์ด ๋ชจ๋ 256 bits๋ผ๊ณ ๋ณด๋ฉด ๋๋ค. int32์ ๊ฒฝ์ฐ 32 bits๋ฅผ ๋จ์๋ก ๊ฐ์ง๋ vector๊ฐ ๋๋ฏ๋ก 8๊ฐ์ฉ ์ฐ์ฐ์ ํ ์ ์๋ค. ์ด ์ข ๋ฏธ๋ฌํ์ง ์์๊น ์๊ฐ๋๊ฒ ์ง๋ง, 10์ด ๊ฑธ๋ฆด๊ฒ์ด 1.25์ด ๊ฑธ๋ฆฐ๋ค๊ณ ์๊ฐํ๋ฉด ํจ๊ณผ๊ฐ ์๋ค. (๋ฌผ๋ก SIMD ์์ฒด์ overhead ๋๋ฌธ์ ์ด๋ณด๋ค๋ ํฅ์ํญ์ด ์ ๊ฒ ์ง๋ง..)
์ฌ์ฉ์ ๋ฐฐ์ด์ ํฌ์ธํฐ์ (__m256i*)์ ๊ฐ์ ํฌ์ธํฐ ๋ณํ์ ์ฌ์ฉํ๋ฉด ๋๊ณ , ์์ ์ฃผ์ ๊ธฐ์ค์ผ๋ก 256 bits ๋งํผ ์ฌ์ฉํ๋ฉด์ ์ฐ์ฐ์ด ์ด๋ฃจ์ด์ง๋ค. load ์ฐ์ฐ๋ ์กด์ฌํ๋๋ฐ, ๊ตณ์ด ํ๊ณ ์ถ๋ค๋ฉด __m256 ์๋ฃํ์๋ค๊ฐ load ์ฐ์ฐ์ ํตํด ๊ธฐ์กด ๋ฐฐ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์๋ค.
๋ง์ง๋ง์ผ๋ก SIMD Instruction๋ค์ immintrin.h ํค๋์์ ์ฐธ๊ณ ํด๋ ์ข๊ณ , ์ด ๊ธ ์๋์ ์ฒจ๋ถํ manual์ ์ฐธ๊ณ ํด๋ ๋๋ค. ์ฌ๋ฌ ๋ฌธ์ ๋ค์ ์ ์ฉ์ ์๋ํ๋ค๋ณด๋ ์๋๋ ์ฐ์ฐ์ modular ์ฐ์ฐ ์ ๋์ธ ๋ฏ ํ๋ค.
PS๋ฅผ ํ๋ฉด์ ์๊พธ ํ๋ง๋ฒ์ ๋น ์ง๋ฉด ์๋๋๋ฐ, ์ ์ผ ๊ณต๋ถํ๊ธฐ ์ฌ๋ฐ๋๊ฒ ์ด๋ฐ ํ๋ง๋ฒ์ด๋ค. :)